package com.nikolaj.kuzan.test;

import com.nikolaj.kuzan.utils.DoubleConverter;
import org.neuroph.core.data.DataSet;
import org.neuroph.core.data.DataSetRow;
import org.neuroph.nnet.BAM;
import org.neuroph.nnet.Hopfield;

import java.util.Arrays;

public class HopfieldSample {

    public static void main(String args[]) {

        DataSet trainingSet = new DataSet(10,10);
        trainingSet.addRow(new double[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, new double[]{0, 0, 0, 0, 0, 1, 1, 1, 1, 1}); // H letter
        trainingSet.addRow(new double[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, new double[]{1, 1, 1, 1, 1, 0, 0, 0, 0, 0}); // I letter



        BAM bam = new BAM(10,10);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);
        bam.learn(trainingSet);



        //print first network weights after learning
        Double[] firstWeight = bam.getWeights();
        double[] dFirstWeight = new double[firstWeight.length];
        for (int i = 0; i < dFirstWeight.length; i++) {
            if (i%9 == 0){
                System.out.println();
            }

            dFirstWeight[i] = firstWeight[i];
            if (dFirstWeight[i] >= 0){
                System.out.print("+" + dFirstWeight[i] + "  ");
            } else {
                System.out.print(dFirstWeight[i] + "  ");
            }
        }



        /*
        //remove first neuron
        firstHopfield.getLayerAt(0).removeNeuronAt(0);
        firstHopfield.getLayerAt(0).removeNeuronAt(2);
        */

        //bam.getLayerAt(0).removeNeuronAt(2);
        Double[] bamWeight = bam.getWeights();
        BAM newBam = new BAM(9,10);
        newBam.setWeights(DoubleConverter.objectDoubleArrToDoubleArr(bamWeight));


        System.out.println();
        System.out.println();

        /*
        //getting network weights after removing neurons
        Double[] newWeight = firstHopfield.getWeights();
        double[] dNewWeight = new double[newWeight.length];

        //printing new weights
        for (int i = 0; i < dNewWeight.length; i++) {
            if (i%7 == 0){
                System.out.println();
            }
            dNewWeight[i] = newWeight[i];
            if (dNewWeight[i] >= 0){
                System.out.print("+" + dNewWeight[i] + "  ");
            } else {
                System.out.print(dNewWeight[i] + "  ");
            }
        }
        */


        /*
        //creating new Hopfield network without removed neurons
        Hopfield newHopfield = new Hopfield(8);
        newHopfield.setWeights(dNewWeight);


        System.out.println();
        System.out.println();

        //getting new Hopfield network weights
        newWeight = newHopfield.getWeights();
        dNewWeight = new double[newWeight.length];

        //printing new Hopfield network weights
        for (int i = 0; i < dNewWeight.length; i++) {
            if (i%7 == 0){
                System.out.println();
            }

            dNewWeight[i] = newWeight[i];
            if (dNewWeight[i] >= 0){
                System.out.print("+" + dNewWeight[i] + "  ");
            } else {
                System.out.print(dNewWeight[i] + "  ");
            }
        }





        */



        // test hopfield network
        System.out.println();
        System.out.println();
        System.out.println("Testing network");

        trainingSet = new DataSet(10);
        trainingSet.addRow(new double[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
        trainingSet.addRow(new double[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        //trainingSet.addRow(new double[]{1, 1, 0, 1, 0, 1, 1, 1});
        //trainingSet.addRow(new double[]{0, 0, 1, 0, 0, 1, 0, 1});

        for (DataSetRow dataRow : trainingSet.getRows()) {

	        bam.setInput(dataRow.getInput());
            bam.calculate();
            bam.calculate();
            bam.calculate();
            bam.calculate();
            bam.calculate();
            bam.calculate();



            double[] networkOutput = bam.getOutput();

            System.out.print("Input: " + Arrays.toString(dataRow.getInput()));
            System.out.println(" Output: " + Arrays.toString(networkOutput));
        }

    }

}